/*
	Copyright (c) 2006-2008, Grant Jones <grant@podtronics.com>.
	All rights reserved.

	Redistribution and use in source and binary forms, with or
	without modification, are permitted provided that the following
	conditions are met:

		Redistributions of source code must retain the above copyright
		notice, this list of conditions and the following disclaimer.
		
		Redistributions in binary form must reproduce the above copyright
		notice, this list of conditions and the following disclaimer in
		the documentation and/or other materials provided with the
		distribution.
		
		Neither the name of the gxjones.com nor the names of its
		contributors may be used to endorse or promote products derived
		from this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
	FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
	COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
	OF THE POSSIBILITY OF SUCH DAMAGE.
	
	http://www.opensource.org/licenses/bsd-license.php
*/
/*
 *  cmap.h
 *  cmap
 *
 *  Created by Grant Jones on 10/28/06.
 *
 *  A basic sorted associative array for C programs.
 */


#ifndef CMAP_H
#define CMAP_H


// If no getpagesize function exists:
#define NO_PAGE_SZ_ALLOC
#define CMAP_LOCKING

#ifdef WIN32
	#define CMAP_PTR	unsigned char
	#ifdef CMAP_LOCKING
		#include <windows.h>
	#endif
#else
	#define CMAP_PTR	void
	#ifdef CMAP_LOCKING
		#include <pthread.h>
	#endif
#endif

#include <assert.h>
/* MEMPOOL_SOFT_DESTROY : disables any actual destruction of a pool
** instead it marks the structure as "destroyed"; assertions are
** enabled when this is defined that will catch post-destroyed 
** pool usage */
/*
#define MEMPOOL_SOFT_DESTROY
*/


/* DEBUG_MEMPOOL : enable verbose mempool creation and destruction
** logs are written to stdout */
/*
** #define DEBUG_MEMPOOL
*/

#define CMAP_POOL_INIT_SZ	1024
/*
** cmap was originally designed to be used with "int" keys (signed or
** unsigned), however, any key size should work.
** #define CMAP_KEY_TYPE		int
*/
#include <sys/types.h>	/* off_t */
#define CMAP_KEY_TYPE		off_t
#define CMAP_PAIR_SZ		(sizeof(CMAP_KEY_TYPE)+sizeof(void*))

/*!
    @struct mempool_page_t
    @abstract Header for one memory pool page
    @discussion 
    @field link Entry for the next page address in the linked-list
    @field alloced Size of the allocated page
	@field next Next allocation location in the page
	@field uid Unique ID of the page in the memory pool. This field is used to identify which page memory is allocated from
	@field mempool the start of raw page data
*/

typedef struct mempool_page_struct
{
	struct mempool_page_struct *link;
	size_t alloced;
	size_t next;
	size_t uid;
	unsigned char mempool[1];
} mempool_page_t;

/*!
    @struct mempool_alloc_info_t
    @abstract Header for a memory allocation chunk from a pool page
    @discussion This structure describes a single memory allocation. The structure is allocated from the mempool.
    @field link Entry for the next memory allocation address in the linked-list
    @field alloc_sz Size of the allocated memory
	@field alloc_loc Offset location from the start of the mempool page
	@field page_id Unique ID of the page in the memory pool. This field is used to identify which page memory is allocated from
	@field name Pointer to a human readable description of the allocation (such as the source file and line)
*/

typedef struct mempool_alloc_info_struct
{
	unsigned long checksum;
	struct mempool_alloc_info_struct *link;
	size_t alloc_sz;
	size_t alloc_loc;
	size_t page_id;
	void *ptr;
	const char *name;
} mempool_alloc_info_t;

/*!
    @struct mempool_t
    @abstract The main mempool data structure
    @discussion This structure describes the entire memory pool.
    @field head Head of the page linked-list. New allocations attempt to be placed on this page first
    @field info_head Head of the allocations description linked-list. Each entry describes a single allocation call from a mempool_malloc* or mempool_realloc* call
	@field free_head Freed memory list
	@field page_sz Size of the next allocated page. This size grows as more pages are allocated.
	@field total_alloced_sz The combined sizes of all pages allocated.
	@field next_page_id The next page UID, this is simply a count of the number of pages.
*/

typedef struct
{
	mempool_page_t *head;
	mempool_alloc_info_t *info_head;
	mempool_alloc_info_t *free_head;
	size_t page_sz;
	size_t total_alloced_sz;
	size_t next_page_id;
	const char *name;
#ifdef MEMPOOL_SOFT_DESTROY
	int destroyed;
#endif	
} mempool_t;



/*!
    @struct cmapActionStruct
    @abstract Describes a differed cmap action
    @discussion Direct interaction with this data is typically not necessary.
    @field link Link to the next differed action, NULL if there are no more actions.
    @field key The key to use during the action
	@field data The data pointer to use for a differed assign action
	@field bRemove Flag describing what action to take when committed. TRUE signals that "key" will be removed, FALSE signals that "data" will be assigned to "key".
*/

typedef struct cmapActionStruct
{
	struct cmapActionStruct *link;
	CMAP_KEY_TYPE key;
	void *data;
	int bRemove;
} cmapActionStruct;

/*!
    @struct cmapStruct
    @abstract The main cmap structure
    @discussion This structure can be allocated by using "cmap_new". Direct interaction with the fields of this structure are typically not necessary.
    @field kd Key-Value data memory. The contents of which is simply key-value pairs in SORTED order.
    @field num Number of key-value pairs in kd
	@field alloced The number of key-value pairs which will fit within the currently allocated kd space.
	@field lock Opaque locking mechanism
	@field deffered_actions A linked-list of actions waiting to be commited. This provides a way to modify the cmap while iterating or enumerating elements.
	@field mempool When cmap mempool usage is enabled this field is used during all memory operations
	@field bOwnsPool Field describing if the cmap owns its own mempool; set to TRUE during cmap_init if the cmap has allocated its own mempool -- meaning it must also destroy it when the cmap_destroy function is called; FALSE, if the cmap does not need to worry about destroying the memory pool.
*/

typedef struct
{
	unsigned char *kd;
	CMAP_KEY_TYPE num;
	CMAP_KEY_TYPE alloced;
	
#ifdef CMAP_LOCKING
#ifdef WIN32
	CRITICAL_SECTION lock;
#else
	pthread_mutex_t lock;
#endif
#endif
	cmapActionStruct *deffered_actions;
	
	mempool_t *mempool;
	int bOwnsPool;
} cmapStruct;

/*!
    @struct cmapEnumStruct
    @abstract cmap Enumeration state structure
    @discussion This structure is used to keep state information of an enumeration procedure
	@field pairptr Pointer to the current cursor position
	@field endptr Pointer to the last element in the cmap
	@field cmap Pointer to the cmap the enumeration is being performed on
*/
typedef struct
{
	CMAP_PTR *pairptr;
	CMAP_PTR *endptr;
	cmapStruct *cmap;
} cmapEnumStruct;

/*!
	@function cmap_new_named
	@abstract Allocates a new cmap from allocator
	@discussion Use this method to allocate a new cmap from an existing memory pool
	@param allocator The memory pool to allocate the new cmap from; this allocator is inherited by the cmap and used in all subsequent memory operations. May be NULL meaning the cmap will create a new pool.
	@param name arbitrary name, useful for debugging. this value is inherited by the mempool
	@result cmap structure pointer
*/
cmapStruct *cmap_new_named( mempool_t *allocator, const char *name );
#define cmap_new( allocator ) cmap_new_named( allocator, __FUNCTION__ )

/*!
	@function cmap_destroy
	@abstract Destroys a cmap created by cmap_new
	@discussion Destroys a cmap created by cmap_new. This operation is a no-op if the cmap does not own it's own memory pool.
	@param cmap pointer to cmap to operate on
*/
void cmap_destroy( cmapStruct *cmap );

/*!
	@function cmap_init
	@abstract Initializes a cmap structure
	@discussion Called by cmap_new; may be called directly if not using cmap_new creator.
	@param cmap pointer to cmap to operate on
	@param allocator memory pool to inherit; if NULL cmap creates a new memory pool (if memory pools are enabled).
	@param named arbitrary name
*/
void cmap_init( cmapStruct *cmap, mempool_t *allocator, const char *named );

/*!
	@function cmap_duplicate
	@abstract Duplicates a cmap
	@discussion Copies the key-value pairs from cmap_src to cmap_dst. If memory pools are enabled, destination is allocated from cmap_dst. cmap_dst must be an initialized and valid cmap.
	@param cmap_dst pointer to destination cmap
	@param cmap_src cmap pointer from which key-value pairs are copied from
*/
void cmap_duplicate( cmapStruct *cmap_dst, cmapStruct *cmap_src );
/*!
	@function cmap_assign
	@abstract Assigns data to a key
	@discussion This is one of the main methods to interact with the cmap. data is assigned to key via this function
	@param cmap pointer to cmap to operate on
	@param key An integer which represents an arbitrary key
	@param data A pointer to arbitrary data
*/
void cmap_assign( cmapStruct *cmap, CMAP_KEY_TYPE key, void *data );

/*!
	@function cmap_assign_new
	@abstract Allocates data and assigns it to key
	@discussion Use this function to allocate data_sz memory from the cmap and assign it to key
	@param cmap pointer to cmap to operate on
	@param key An integer which represents an arbitrary key
	@param data_sz Size of the data to be allocated
	@result A pointer to a new chunk of memory of size data_sz; NULL on error
*/
void *cmap_assign_new( cmapStruct *cmap, CMAP_KEY_TYPE key, size_t data_sz );

/*!
	@function cmap_remove
	@abstract Removes key from the cmap
	@discussion Use this function to remove a key from the cmap
	@param cmap pointer to cmap to operate on
	@param key An integer which represents an arbitrary key
	@result A pointer to whatever key data was stored; NULL if not found
*/
void *cmap_remove( cmapStruct  *cmap, CMAP_KEY_TYPE key );

/*!
	@function cmap_lookup
	@abstract Retrieves data for the specified key from the cmap
	@discussion Use this function to retrieve the data associated with key from the cmap.
	@param cmap pointer to cmap to operate on
	@param key An integer which represents an arbitrary key
	@result A pointer to whatever key data was stored; NULL if not found
*/
void *cmap_lookup( cmapStruct *cmap, CMAP_KEY_TYPE key );


/*!
	@function cmap_gethighestkey
	@abstract Get the highest key value in the cmap
	@discussion Use this function to get the highest key contained in the cmap
	@param cmap pointer to cmap to operate on
	@result The highest key in the cmap; Zero if there are no keys in the cmap
*/
CMAP_KEY_TYPE cmap_gethighestkey( cmapStruct *cmap );
/*!
	@function cmap_getlowestkey
	@abstract Get the lowest key value in the cmap
	@discussion Use this function to get the lowest key contained in the cmap
	@param cmap pointer to cmap to operate on
	@result The lowest key in the cmap; Zero if there are no keys in the cmap
*/
CMAP_KEY_TYPE cmap_getlowestkey( cmapStruct *cmap );

/*!
	@function cmap_iterate
	@abstract Calls iterFunc for each item in the cmap in order
	@discussion Use this function to call a function on each item in the cmap. Note: direct modification (assign or remove) of the cmap is NOT allowed and may leave the cmap in an inconsistent state.  Use deffered actions to perform delayed assign or removes.
	@param cmap pointer to cmap to operate on
	@param ctx An arbitrary context pointer
	@param iterFunc The receiving callback function.
*/
void cmap_iterate( cmapStruct *cmap, void *ctx, void (*iterFunc)(CMAP_KEY_TYPE key, void *data, void *ctx) );

/*!
	@function cmap_iterate_r
	@abstract Calls iterFunc for each item in the cmap in reverse order
	@discussion Use this function to call a function on each item in the cmap in reverse order. Note: direct modification (assign or remove) of the cmap is NOT allowed and may leave the cmap in an inconsistent state.  Use deffered actions to perform delayed assign or removes.
	@param cmap pointer to cmap to operate on
	@param ctx An arbitrary context pointer
	@param iterFunc The receiving callback function.
*/
void cmap_iterate_r( cmapStruct *cmap, void *ctx, void (*iterFunc)(CMAP_KEY_TYPE key, void *data, void *ctx) );

/*!
	@function cmap_iterate2
	@abstract Calls iterFunc for each item in the cmap in order
	@discussion Use this function to call a function on each item in the cmap in order. Note: direct modification (assign or remove) of the cmap is NOT allowed and may leave the cmap in an inconsistent state.  Use deffered actions to perform delayed assign or removes.
	@param cmap pointer to cmap to operate on
	@param ctx An arbitrary context pointer
	@param iterFunc The receiving callback function. NOTE: the first argument is the cmap from which the key/value pairs originate from, this value may be used to perform deffered actions on the cmap.
*/
void cmap_iterate2( cmapStruct *cmap, void *ctx, void (*iterFunc)(cmapStruct *, CMAP_KEY_TYPE key, void *data, void *ctx) );

/*!
	@function cmap_enum
	@abstract Initializes an enumeration structure
	@discussion Called before cmap_enum_next, to intialize the enumeration state structure
	@param cmap pointer to cmap to operate on
	@param e pointer to a cmapEnumStruct which will be initailized with a new enumeration state
*/
void cmap_enum( cmapStruct *cmap, cmapEnumStruct *e );
/*!
	@function cmap_enum_next
	@abstract Retrieves the next key/value pair from the current enumeration state
	@discussion Call cmap_enum_next with an intialized enumeration state structure until the return value is NULL to enumerate all items in a cmap. Note: direct modification (assign or remove) of the cmap is NOT allowed and may leave the cmap in an inconsistent state. Use deffered actions to perform delayed assign or removes.
	@param cmap pointer to cmap to operate on
	@param e pointer to a cmapEnumStruct which will be initailized with a new enumeration state
*/
void *cmap_enum_next( cmapEnumStruct *e, CMAP_KEY_TYPE *key_ptr );

/*!
	@function cmap_deferred_remove
	@abstract Queues up a deffered remove action on the cmap
	@discussion Intended to be used during an iterate/enumeration procedure where direct modification of the cmap is not allowed. Be sure to call cmap_commit_deffered_actions when direct modification to the cmap is allowed (outside an iterate/enumerate)
	@param cmap pointer to cmap to operate on
	@param key The key to remove from the cmap
*/
void cmap_deferred_remove( cmapStruct *cmap, CMAP_KEY_TYPE key );

/*!
	@function cmap_deferred_assign
	@abstract Queues up a deffered remove action on the cmap
	@discussion Intended to be used during an iterate/enumeration procedure where direct modification of the cmap is not allowed. Be sure to call cmap_commit_deffered_actions when direct modification to the cmap is allowed (outside an iterate/enumerate)
	@param cmap pointer to cmap to operate on
	@param key The key to assign data to
	@param data pointer to data to be assign
*/
void cmap_deferred_assign( cmapStruct *cmap, CMAP_KEY_TYPE key, void *data );

/*!
	@function cmap_commit_deferred_actions
	@abstract Commits all currently deferred actions 
	@discussion After using cmap_deferred_assign and cmap_deferred_remove call this function to actually change the cmap. Ensure that the cmap is in the correct state to receive changes(outside an iterate/enumerate).
	@param cmap pointer to cmap to operate on
*/
void cmap_commit_deferred_actions( cmapStruct *cmap );

/*!
	@function cmap_lock
	@abstract Convience function for locking an entire cmap
	@discussion cmap_lock does not prevent other threads from performing operations on a cmap. This means all threads must use cmap_lock/cmap_unlock pairs before any cmap operation which would cause modification. If only one thread uses a cmap locking is not needed. All assign/remove operations would require cmap_lock/cmap_unlock be called if multiple threads access a cmap -- this includes deferred actions. Iteration/enumeration also require locking to maintain a consistent state.
	@param cmap pointer to cmap to operate on
*/
void cmap_lock( cmapStruct *cmap );
/*!
	@function cmap_unlock
	@abstract Convience function for unlocking an entire cmap locked by cmap_lock
	@discussion See cmap_lock for further discussion
	@param cmap pointer to cmap to operate on
*/
void cmap_unlock( cmapStruct *cmap );

#define cmap_push( c, data ) cmap_assign( (c), (c)->num, data )
#define cmap_pop( c ) cmap_remove( (c), (c)->num-1 )
#define cmap_head( c ) cmap_lookup( (c), (c)->num-1 )

#ifndef WIN32
/* Misc string capabilities */
// These functions require vsnprintf which may not be available for a win32 build (I don't remember/care what the win32 equivalent is called)
#include <stdarg.h>

/*!
	@function cmap_str_append_bytes
	@abstract Convience function for aid creating strings
	@discussion 
	@param str pointer to cmap to operate on
	@result A newly allocated buffer containing the input data. This is allocated from the cmap mempool.
*/
char *cmap_str_append_bytes( cmapStruct *str, const char *data, size_t data_sz );
/*!
	@function cmap_str_concat
	@abstract Convience function for creating formatted strings
	@discussion fmt may be arbitrarily sized assuming infinite memory available; cmap_str* functions are designed to be used on cmaps where all data values are length-prefixed strings (p-string stylish).
	@param str pointer to cmap to operate on
	@result A newly allocated string containing the formatted string. This is allocated from the cmap mempool.
*/
char *cmap_str_concat( cmapStruct *str, const char *fmt, ... );
/*!
	@function cmap_str_concat
	@abstract Convience function for joining strings in a cmap
	@discussion Creates one string joining all strings in a cmap together. The cmap must contain only contain buffers containing proper length-prefixed strings.
	@param str pointer to cmap to operate on
	@param len_out filled with the resulting length of the joined string, undefined if an error occurs. This length count INCLUDES the NULL-terminator which is ALWAYS added to the end of the string
	@result A newly allocated string containing the joined strings. This is allocated from the cmap mempool. 
*/
char *cmap_str_join( cmapStruct *str, size_t *len_out );
#endif	// #ifndef WIN32

/* Hash Functions */
/*!
	@function djb2_hash
	@abstract Convience function for hashing a string
	@discussion Efficient hash function described by Dan Bernstein in comp.lang.c (http://cr.yp.to/djb.html)
	@param k An ASCII string
	@param keylen Length of the string, k
	@result The hash of string k
*/
unsigned long djb2_hash(const char *k, unsigned long keylen);


/* Memory pool functions */
/*!
	@function mempool_init_named
	@abstract Initalizes a memory pool
	@discussion Must be called before using a memory pool
	@param pool The pool structure to initialize
	@param first_sz The first page size to allocate
	@param name an arbitrary name, set to the calling functions name when using the mempool_init macro
*/
void mempool_init_named( mempool_t *pool, size_t first_sz, const char *name );

#define mempool_init( pool, first_sz ) mempool_init_named( pool, first_sz, __FUNCTION__ );

/*!
	@function mempool_newpage
	@abstract Allocates a fresh page for the memory pool
	@discussion Called by the various mempool allocation routines. Should not be called directly.
	@param pool The memory pool
*/
int mempool_newpage( mempool_t *pool );

/*!
	@function mempool_destroy
	@abstract Destroys a memory pool initialized by mempool_init, freeing all pages allocated.
	@discussion Use this to free and destroy a memory pool
	@param pool The memory pool
*/
void mempool_destroy( mempool_t *pool );

/*!
	@function mempool_malloc
	@abstract Allocates len amount of memory
	@discussion Convience function which simply calles mempool_malloc_named with "untitled" as the name
	@param pool The memory pool
	@param len Length of memory requested
	@result a newly allocated chunk of memory of size len; NULL on error
*/
void *mempool_malloc( mempool_t *pool, size_t len );

/*!
	@function mempool_malloc
	@abstract Allocates len amount of memory, labels with name
	@discussion Alloactes len amount of memory from the memory pool; also labels with name for debug purposes
	@param pool The memory pool
	@param len Length of memory requested	
	@result a newly allocated chunk of memory of size len; NULL on error
*/
void *mempool_malloc_named( mempool_t *pool, size_t len, const char *name );	// preferred

/*!
	@function mempool_malloc
	@abstract Allocates len amount of memory, labels with name
	@discussion Alloactes len amount of memory from the memory pool; also labels with name for debug purposes. Should not be called directly.
	@param pool The memory pool
	@param len Length of memory requested
	@param page_loc On successful allocation filled with the location allocated in the page
	@param page_id On successfl allocation filled with the page UID
	@result a newly allocated chunk of memory of size len; NULL on error
*/
void *mempool_malloc_raw( mempool_t *pool, size_t len, size_t *page_loc, size_t *page_id );

/*!
	@function mempool_free
	@abstract Releases memory allocated by one of the mempool_malloc* or mempool_realloc* routines
	@discussion Would free memory from the mempool making it available again. Not currently implemented.
	@param pool The memory pool
	@param buf The buffer to free which was allocated by the mempool
*/
void mempool_free( mempool_t *pool, void *buf);

/*!
	@function mempool_realloc
	@abstract Resizes an existing buffer. Uses a name of "untitled"
	@discussion Resizes an existing buffer "buf" to size "len"; copies as much data as possible into the new buffer.
	@param pool The memory pool
	@param buf The buffer to resize which was allocated by the mempool
	@param len The desired length of the new buffer
	@result a newly allocated or resized memory buffer; NULL on error
*/
void *mempool_realloc( mempool_t *pool, void *buf, size_t len );

/*!
	@function mempool_realloc
	@abstract Resizes an existing buffer.
	@discussion Resizes an existing buffer "buf" to size "len"; copies as much data as possible into the new buffer.
	@param pool The memory pool
	@param buf The buffer to resize which was allocated by the mempool
	@param len The desired length of the new buffer
	@param bname A name to associate with the new buffer, used for debugging
	@result a newly allocated or resized memory buffer; NULL on error
*/

void *mempool_realloc_named( mempool_t *pool, void *buf, size_t len, const char *bname );


/*!
	@function mempool_describe
	@abstract Describes the contents of the memory pool.
	@discussion Used to describe all memory allocations in the specified pool. Output is sent to stdout via printf.
	@param pool The memory pool
*/
void mempool_describe( mempool_t *pool );


/*!
	@function mempool_locate_sz
	@abstract Locates an allocation based on it's pointer.
	@discussion Used during realloc to find the old memory size. Note: Linear search so
		reallocs in general shouldn't be used very often.
	@param pool The memory pool
	@param locate_ptr The allocation to find
	@result The size of the old allocation, or zero if it was not found
*/
size_t mempool_locate_sz( mempool_t *pool, void *locate_ptr );

/*!
	@function mempool_gen_checksum
	@abstract returns a checksum of the header
	@discussion 
	@param pool the memory pool to check
	@result a checksum
*/
unsigned long mempool_gen_checksum( mempool_alloc_info_t *info );

/*!
	@function mempool_integrity
	@abstract asserts that the allocation headers have not been overwritten
	@discussion this check is only enabled if MEMPOOL_SOFT_DESTROY is enabled.
				also note there is a severe performance penalty for using this
				feature.
	@param pool the memory pool to check
	@result if assertion fails the program will abort, this may not be the desired behavior
*/
void mempool_integrity( mempool_t *pool );


/*!
	@function mempool_assert_alive
	@abstract asserts that the pool hasn't been destroyed
	@discussion this check is only enabled if MEMPOOL_SOFT_DESTROY is enabled
	@param pool the memory pool to check
*/
#ifdef MEMPOOL_SOFT_DESTROY
	#define mempool_assert_alive( pool ) assert( pool->destroyed == 0 ), mempool_integrity(pool);
#else
	#define mempool_assert_alive( pool ) ;
#endif

//#define NO_MEMPOOL
#ifdef NO_MEMPOOL
	#ifdef DEBUG_MALLOC
		#define chMalloc(sz) (printf("%s: malloc: %d bytes\n", __FUNCTION__, sz), malloc(sz))
		#define chFree(buf) (printf("%s(%d): free %x\n", __FUNCTION__,__LINE__, buf), free(buf))
		#define chRealloc(buf,sz) (printf("%s: realloc(buf: %x, sz: %d)\n", __FUNCTION__, buf, sz),realloc(buf,sz))
	#else
		#define chMalloc(sz) malloc(sz)
		#define chFree(buf) free(buf)
		#define chRealloc(buf,sz) realloc(buf,sz)
	#endif
#else	// Use MEMPOOL
	#define chMalloc(sz) (mempool_malloc_named(cmap->mempool,sz, __FUNCTION__))
	#define chFree(buf) (mempool_free(cmap->mempool,buf))
	#define chRealloc(buf,sz) (mempool_realloc_named(cmap->mempool,buf,sz, __FUNCTION__))
#endif



#endif
